package com.kexio.user.controller;

import java.util.List;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kexio.auth.annotation.RateLimit;
import com.kexio.auth.annotation.RequiresPermission;
import com.kexio.auth.util.AuthContextUtils;
import com.kexio.common.dto.PageResponse;
import com.kexio.common.dto.Result;
import com.kexio.common.page.PageConverters;
import com.kexio.common.page.PageQuery;
import com.kexio.common.page.PageUtils;
import com.kexio.user.dto.RoleDTO;
import com.kexio.user.dto.RoleUserInfo;
import com.kexio.user.entity.Permission;
import com.kexio.user.entity.Role;
import com.kexio.user.entity.User;
import com.kexio.user.service.RoleService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;

/**
 * 角色管理控制器
 * 
 * 提供角色管理相关的REST API，包括：
 * - 角色的增删改查
 * - 角色权限分配
 * - 角色用户管理
 * - 角色数据权限设置
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
@RestController
@RequestMapping("/roles")
@Tag(name = "角色管理", description = "角色管理相关API")
public class RoleController {
    
    private static final Logger logger = LoggerFactory.getLogger(RoleController.class);
    
    @Autowired
    private RoleService roleService;
    
    // ==================== 角色CRUD API ====================
    
    /**
     * 创建角色
     */
    @PostMapping
    @RequiresPermission("role:create")
    @RateLimit(count = 20, time = 1)
    @Operation(summary = "创建角色", description = "创建新的角色")
    public Result<RoleDTO> createRole(
            @Valid @RequestBody RoleDTO request) {
        
        logger.info("创建角色请求: roleCode={}, tenantId={}", 
            request.getRoleCode(), AuthContextUtils.getCurrentTenantId());
        
        request.clearIdsForCreate();
        request.validate();
        
        // 转换DTO到Role实体
        Role role = request.toEntity();
        role = roleService.createRole(role);
        RoleDTO roleDTO = RoleDTO.fromEntity(role);
        
        logger.info("创建角色成功: roleId={}, roleCode={}", 
            role.getId(), role.getCode());
        
        return Result.success("角色创建成功", roleDTO);
    }
    
    /**
     * 更新角色信息
     */
    @PutMapping("/{roleId}")
    @RequiresPermission("role:update")
    @RateLimit(count = 30, time = 1)
    @Operation(summary = "更新角色信息", description = "更新指定角色的信息")
    public Result<RoleDTO> updateRole(
            @Parameter(description = "角色ID") @PathVariable String roleId,
            @Valid @RequestBody RoleDTO request) {
        
        logger.info("更新角色请求: roleId={}, tenantId={}", 
            roleId, AuthContextUtils.getCurrentTenantId());
        
        request.setRoleId(roleId);
        request.validate();
        
        // 转换DTO到Role实体
        Role role = request.toEntity();
        role = roleService.updateRole(roleId, role);
        RoleDTO roleDTO = RoleDTO.fromEntity(role);
        
        logger.info("更新角色成功: roleId={}, roleCode={}", 
            role.getId(), role.getCode());
        
        return Result.success("角色更新成功", roleDTO);
    }
    
    /**
     * 获取角色详情
     */
    @GetMapping("/{roleId}")
    @RequiresPermission("role:query")
    @Operation(summary = "获取角色详情", description = "获取指定角色的详细信息")
    public Result<RoleDTO> getRole(
            @Parameter(description = "角色ID") @PathVariable String roleId) {
        
        logger.debug("获取角色详情请求: roleId={}", roleId);
        
        Role role = roleService.getRoleById(roleId);
        
        if (role == null) {
            logger.warn("角色不存在: roleId={}", roleId);
            return Result.error("角色不存在");
        }
        
        RoleDTO roleDTO = RoleDTO.fromEntity(role);
        
        logger.debug("获取角色详情成功: roleId={}, roleCode={}", 
            role.getId(), role.getCode());
        
        return Result.success("获取成功", roleDTO);
    }
    
    /**
     * 删除角色
     */
    @DeleteMapping("/{roleId}")
    @RequiresPermission("role:delete")
    @RateLimit(count = 10, time = 1)
    @Operation(summary = "删除角色", description = "删除指定角色")
    public Result<Void> deleteRole(
            @Parameter(description = "角色ID") @PathVariable String roleId) {
        
        logger.info("删除角色请求: roleId={}, tenantId={}", 
            roleId, AuthContextUtils.getCurrentTenantId());
        
        boolean deleted = roleService.deleteRole(roleId);
        
        if (!deleted) {
            logger.warn("角色删除失败，可能角色不存在: roleId={}", roleId);
            return Result.error("角色不存在或已被删除");
        }
        
        logger.info("角色删除成功: roleId={}", roleId);
        
        return Result.<Void>success("角色删除成功", null);
    }
    
    // ==================== 角色查询API ====================
    
    /**
     * 分页查询角色列表
     */
    @GetMapping
    @RequiresPermission("role:query")
    @Operation(summary = "分页查询角色", description = "根据条件分页查询角色列表")
    public Result<PageResponse<RoleDTO>> queryRoles(
            @Parameter(description = "角色编码") @RequestParam(required = false) String roleCode,
            @Parameter(description = "角色名称") @RequestParam(required = false) String roleName,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status,
            @Parameter(description = "分页参数") PageQuery pageQuery) {
        
        logger.debug("分页查询角色请求: current={}, size={}", 
            (pageQuery != null ? pageQuery.getCurrent() : null), (pageQuery != null ? pageQuery.getSize() : null));
        
        long current = PageUtils.current(pageQuery);
        long size = PageUtils.size(pageQuery);
        logger.info("查询角色列表: current={}, size={}, roleCode={}, roleName={}, status={}", 
                   current, size, roleCode, roleName, status);
        
        // 实现带条件的分页查询
        Page<Role> rolePage;
        if (StringUtils.hasText(roleCode) || 
            StringUtils.hasText(roleName) || 
            status != null) {
            // 使用带条件的分页查询
            rolePage = roleService.getRolePage(current, size, roleCode, roleName, status);
        } else {
            rolePage = roleService.getRolePage(current, size);
        }
        
        // 转换为DTO
        PageResponse<RoleDTO> response = PageConverters.map(
            rolePage.getRecords(),
            rolePage.getTotal(),
            rolePage.getCurrent(),
            rolePage.getSize(),
            RoleDTO::fromEntity
        );
        
        logger.debug("分页查询角色成功: total={}, current={}, size={}", 
            rolePage.getTotal(), rolePage.getCurrent(), rolePage.getSize());
        
        return Result.success("查询成功", response);
    }
    
    /**
     * 获取所有角色（不分页）
     */
    @GetMapping("/all")
    @RequiresPermission("role:query")
    @Operation(summary = "获取所有角色", description = "获取当前租户下的所有角色")
    public Result<List<RoleDTO>> getAllRoles() {
        
        logger.debug("获取所有角色请求: tenantId={}", AuthContextUtils.getCurrentTenantId());
        
        List<Role> roles = roleService.getAllRoles();
        
        // 转换为DTO
        List<RoleDTO> roleDTOs = PageConverters.mapList(roles, RoleDTO::fromEntity);
        
        logger.debug("获取所有角色成功: count={}", roles.size());
        
        return Result.success("获取成功", roleDTOs);
    }
    
    // ==================== 角色权限管理API ====================
    
    /**
     * 为角色分配权限
     */
    @PostMapping("/{roleId}/permissions")
    @RequiresPermission("role:assign-permission")
    @RateLimit(count = 30, time = 1)
    @Operation(summary = "分配角色权限", description = "为指定角色分配权限")
    public Result<Void> assignPermissions(
            @Parameter(description = "角色ID") @PathVariable String roleId,
            @RequestBody List<String> permissionIds) {
        
        logger.info("分配角色权限请求: roleId={}, permissionCount={}", 
            roleId, permissionIds != null ? permissionIds.size() : 0);
        
        String operatorId = AuthContextUtils.getCurrentUserId();
        
        boolean assigned = roleService.assignPermissions(roleId , permissionIds, operatorId);
        
        if (!assigned) {
            return Result.error("角色不存在");
        }
        
        logger.info("分配角色权限成功: roleId={}, permissionCount={}, 权限将立即生效", 
            roleId, permissionIds != null ? permissionIds.size() : 0);
        
        return Result.<Void>success("权限分配成功，已立即生效", null);
    }
    
    /**
     * 获取角色的权限列表
     */
    @GetMapping("/{roleId}/permissions")
    @RequiresPermission("role:query")
    @Operation(summary = "获取角色权限", description = "获取指定角色的权限列表")
    public Result<List<String>> getRolePermissions(
            @Parameter(description = "角色ID") @PathVariable String roleId) {
        
        logger.debug("获取角色权限请求: roleId={}", roleId);
        
        List<Permission> permissions = roleService.getRolePermissions(roleId);
        // 转换为权限ID列表（与实体一致的 String 类型）
        List<String> permissionIds = permissions.stream()
                .map(Permission::getId)
                .collect(Collectors.toList());
        
        logger.debug("获取角色权限成功: roleId={}, permissionCount={}", 
            roleId, permissionIds.size());
        
        return Result.success("获取成功", permissionIds);
    }
    
    // ==================== 角色用户管理API ====================
    
    /**
     * 获取角色的用户列表
     */
    @GetMapping("/{roleId}/users")
    @RequiresPermission("role:query")
    @Operation(summary = "获取角色用户", description = "获取拥有指定角色的用户列表")
    public Result<List<RoleUserInfo>> getRoleUsers(
            @Parameter(description = "角色ID") @PathVariable String roleId) {
        
        logger.debug("获取角色用户请求: roleId={}", roleId);
        
        List<User> users = roleService.getRoleUsers(roleId);
        // 转换为RoleUserInfo，实现转换逻辑
        List<RoleUserInfo> userInfos = users.stream()
                .map(user -> {
                    RoleUserInfo info = new RoleUserInfo();
                    info.setUserId(user.getId());
                    info.setUsername(user.getUsername());
                    info.setNickname(user.getNickname());
                    info.setDeptId(user.getDeptId());
                    info.setStatus(user.getStatus());
                    info.setIsLocked(user.getIsLocked());
                    info.setLastLoginTime(user.getLastLoginTime());
                    
                    return info;
                })
                .collect(Collectors.toList());
        
        logger.debug("获取角色用户成功: roleId={}, userCount={}", 
            roleId, users.size());
        
        return Result.success("获取成功", userInfos);
    }
    
    // ==================== 角色菜单管理API ====================
    
    /**
     * 为角色分配菜单
     */
    @PostMapping("/{roleId}/menus")
    @RequiresPermission("role:assign-menu")
    @RateLimit(count = 30, time = 1)
    @Operation(summary = "分配角色菜单", description = "为指定角色分配菜单")
    public Result<Void> assignMenus(
            @Parameter(description = "角色ID") @PathVariable String roleId,
            @RequestBody List<String> menuIds) {
        
        logger.info("分配角色菜单请求: roleId={}, menuCount={}", 
            roleId, menuIds != null ? menuIds.size() : 0);
        
        String operatorId = AuthContextUtils.getCurrentUserId();
        
        boolean assigned = roleService.assignMenus(roleId, menuIds, operatorId);
        
        if (!assigned) {
            return Result.error("角色不存在");
        }
        
        logger.info("分配角色菜单成功: roleId={}, menuCount={}", 
            roleId, menuIds != null ? menuIds.size() : 0);
        
        return Result.<Void>success("菜单分配成功", null);
    }
    
    /**
     * 获取角色的菜单列表
     */
    @GetMapping("/{roleId}/menus")
    @RequiresPermission("role:query")
    @Operation(summary = "获取角色菜单", description = "获取指定角色的菜单列表")
    public Result<List<String>> getRoleMenus(
            @Parameter(description = "角色ID") @PathVariable String roleId) {
        
        logger.debug("获取角色菜单请求: roleId={}", roleId);
        
        List<com.kexio.user.entity.Menu> menus = roleService.getRoleMenus(roleId, null);
        // 转换为菜单ID列表
        List<String> menuIds = menus.stream()
                .map(com.kexio.user.entity.Menu::getId)
                .collect(Collectors.toList());
        
        logger.debug("获取角色菜单成功: roleId={}, menuCount={}", 
            roleId, menuIds.size());
        
        return Result.success("获取成功", menuIds);
    }
    
    // ==================== 角色统计 ====================
    
    /**
     * 获取角色统计信息
     */
    @GetMapping("/statistics")
//    @RequiresPermission("role:statistics")
    @Operation(summary = "获取角色统计信息", description = "获取角色的统计数据")
    public Result<RoleStatistics> getRoleStatistics() {
        
        logger.debug("获取角色统计信息请求: tenantId={}", AuthContextUtils.getCurrentTenantId());
        
        // 实现角色统计逻辑
        RoleStatistics statistics = new RoleStatistics();
        
        // 获取所有角色
        List<Role> allRoles = roleService.getAllRoles();
        
        if (allRoles != null && !allRoles.isEmpty()) {
            statistics.setTotalRoles(allRoles.size());
            
            // 状态统计
            long enabledCount = allRoles.stream()
                    .filter(role -> role.getStatus() != null && role.getStatus() == 1)
                    .count();
            
            statistics.setEnabledRoles((int) enabledCount);
            statistics.setDisabledRoles(allRoles.size() - (int) enabledCount);
            
            // 统计有用户的角色数量
            int rolesWithUsers = 0;
            int rolesWithPermissions = 0;
            int totalUserCount = 0;
            int totalPermissionCount = 0;
            
            for (Role role : allRoles) {
                // ✓ 保留此catch：循环中单个角色统计失败时继续处理其他角色
                try {
                    // 统计角色用户数
                    Long userCount = roleService.countRoleUsers(role.getId(), null);
                    if (userCount != null && userCount > 0) {
                        rolesWithUsers++;
                        totalUserCount += userCount.intValue();
                    }
                    
                    // 统计角色权限数
                    List<Permission> permissions = roleService.getRolePermissions(role.getId());
                    if (permissions != null && !permissions.isEmpty()) {
                        rolesWithPermissions++;
                        totalPermissionCount += permissions.size();
                    }
                } catch (Exception ex) {
                    logger.warn("统计角色{}的用户/权限数量失败: {}", role.getId(), ex.getMessage());
                }
            }
            
            statistics.setRolesWithUsers(rolesWithUsers);
            statistics.setRolesWithPermissions(rolesWithPermissions);
            
            // 计算平均值
            statistics.setAverageUsersPerRole(!allRoles.isEmpty() ? 
                (double) totalUserCount / allRoles.size() : 0.0);
            statistics.setAveragePermissionsPerRole(!allRoles.isEmpty() ? 
                (double) totalPermissionCount / allRoles.size() : 0.0);
            
            logger.debug("角色统计完成: 总数={}, 启用={}, 禁用={}, 有用户={}, 有权限={}", 
                       statistics.getTotalRoles(), statistics.getEnabledRoles(),
                       statistics.getDisabledRoles(), statistics.getRolesWithUsers(),
                       statistics.getRolesWithPermissions());
        } else {
            // 没有角色数据时的默认统计
            statistics.setTotalRoles(0);
            statistics.setEnabledRoles(0);
            statistics.setDisabledRoles(0);
            statistics.setRolesWithUsers(0);
            statistics.setRolesWithPermissions(0);
            statistics.setAverageUsersPerRole(0.0);
            statistics.setAveragePermissionsPerRole(0.0);
        }
        
        logger.debug("获取角色统计信息成功: total={}", statistics.getTotalRoles());
        
        return Result.success("获取成功", statistics);
    }
    
    /**
     * 角色统计信息DTO
     */
    public static class RoleStatistics {
        private Integer totalRoles = 0;
        private Integer enabledRoles = 0;
        private Integer disabledRoles = 0;
        private Integer rolesWithUsers = 0;
        private Integer rolesWithPermissions = 0;
        private Double averageUsersPerRole = 0.0;
        private Double averagePermissionsPerRole = 0.0;
        
        // Getters and Setters
        public Integer getTotalRoles() { return totalRoles; }
        public void setTotalRoles(Integer totalRoles) { this.totalRoles = totalRoles; }
        
        public Integer getEnabledRoles() { return enabledRoles; }
        public void setEnabledRoles(Integer enabledRoles) { this.enabledRoles = enabledRoles; }
        
        public Integer getDisabledRoles() { return disabledRoles; }
        public void setDisabledRoles(Integer disabledRoles) { this.disabledRoles = disabledRoles; }
        
        public Integer getRolesWithUsers() { return rolesWithUsers; }
        public void setRolesWithUsers(Integer rolesWithUsers) { this.rolesWithUsers = rolesWithUsers; }
        
        public Integer getRolesWithPermissions() { return rolesWithPermissions; }
        public void setRolesWithPermissions(Integer rolesWithPermissions) { this.rolesWithPermissions = rolesWithPermissions; }
        
        public Double getAverageUsersPerRole() { return averageUsersPerRole; }
        public void setAverageUsersPerRole(Double averageUsersPerRole) { this.averageUsersPerRole = averageUsersPerRole; }
        
        public Double getAveragePermissionsPerRole() { return averagePermissionsPerRole; }
        public void setAveragePermissionsPerRole(Double averagePermissionsPerRole) { this.averagePermissionsPerRole = averagePermissionsPerRole; }
    }
}
